/***************************************************************************************
 * @file master.js
 * @author TKONIY
 * @description 
 * Master implementation with websocket package[https://www.npmjs.com/package/websocket]
 * and some nodejs modules. Express package[https://www.npmjs.com/package/express] is 
 * used only to show how to build websocket server upon a http server.
 * 
 * 时钟事件： 
 *          间隔一段时间遍历clientArray给符合条件的client发消息, client的类型为Client, 包含了一个从
 *          机的所有信息以及唯一的标识符id。
 * 其他事件: 
 *          以m:开头的事件为自定义事件, 表示接收到某个特定类型的消息, 如 m:airControl 表示airControl
 *          消息。实现方式是:接收到消息后提取event字段并添加上m:开头, 并将data字段作为参数使用emit()分发。
 *****************************************************************************************/
const express = require('express')
const app = express()
const server = app.listen(5000)
const WebSocket = require('websocket').server


/**global variables */
initialClientID = 0
const newClientID = () => initialClientID++
function Client(socket) {
    this.id = newClientID()
    this.socket = socket
    this.userID = null
    this.roomID = null
    this.online = false
    this.cost = 0
    this.temperature = 0
    this.expectSpeed = 0
}
var clientArray = []
const temperature = 22
const mode = 'cold'
const wss = new WebSocket({
    httpServer: server,
    autoAcceptConnections: true
})


/**timer events */
timerSendAir = setInterval(() => {
    clientArray
        .filter(c => c.online && c.expectSpeed)
        .forEach(c => {
            c.socket.send(JSON.stringify({
                event: 'air',
                data: {
                    temperature: temperature,
                    speed: c.expectSpeed
                }
            }))
        })
}, 1000)

timerSendStatus = setInterval(() => {
    clientArray
        .forEach(c => {
            c.socket.send(JSON.stringify({
                event: 'status',
                data: {
                    mode: mode,
                    cost: c.cost
                }
            }))
        })
}, 1000)


/**websocket events*/
wss.on('connect', (socket) => {

    let client = new Client(socket)
    clientArray.push(client)
    console.log('New connection: ' + client.id)


    socket.on('close', (code, reason) => {
        console.log('Connection:' + client.id +
            ' closed ' + code + ': ' + reason)
        clientArray.filter(c => c.socket != socket)
    })

    socket.on('message', (message) => {
        if (message.type === 'utf8') {
            const ev = JSON.parse(message.utf8Data)
            socket.emit('m:' + ev['event'], ev['data'], socket)
        }
    })

    socket.on('m:login', (data) => {
        client.roomID = data['roomID']
        client.userID = data['userID']
        client.online = true

        console.log('[login:' + client.id + ']' +
            ' roomID:' + client.roomID +
            ' userID:' + client.userID
        )
    })

    socket.on('m:logout', (data) => {
        const roomID = data['roomID']
        const userID = data['userID']
        if (roomID == client.roomID &&
            userID == client.userID) {
            client.online = false
            console.log('[logout:' + client.id + ']' +
                ' roomID:' + roomID +
                ' userID:' + userID
            )
        }
    })

    socket.on('m:airControl', (data) => {
        client.expectSpeed = data['speed']
        if (client.expectSpeed == 0) {
            console.log('[airControl:' + client.id + '] stop air.')
        } else {
            console.log('[airControl:' + client.id + '] expected speed:' + client.expectSpeed)
        }
    })

    socket.on('m:status', (data) => {
        client.temperature = data['temperature']
        console.log('[status:' + client.id + '] temperature:' + client.temperature)
    })
})

